package logo.sys;

import logo.lang.*;

import java.util.*;

/** Dictionary class to support runtime bookkeeping needed by the
    interpreter. */
public class LogoDictionary {
    LogoDictionary parent = null;
    Hashtable<String, LogoVal> tbl;
    
    /** Create a new dictionary capable of storing Logo bindings. */
    public LogoDictionary() {
	super();
	tbl = new Hashtable<String, LogoVal>();
    }

    /** Create a new dictionary capable of storing Logo bindings. */
    protected LogoDictionary(LogoDictionary p) {
	parent = p;
	tbl = new Hashtable<String, LogoVal>();
    }
    
    /** Return the value associated with the given name in this dictionary.
	Returns null if there is no such association.
    */
    public LogoVal get(String name) throws LogoException {
	LogoVal result = (LogoVal)tbl.get(name);
	if (result == null)
	    if (parent != null)
		return parent.get(name);
	    else
		throw new LogoLookupException(name);
	else 
	    return result;
    }

    /** Binds the given name to the given value in this dictionary. */
    public void put(String var, LogoVal value) {
	tbl.put(var, value);
    }

    /** Return the underlying set of bindings as an abstract Map.
	(For internal use only).
    */
    protected Map<String, LogoVal> getMap() {
	return tbl;
    }

    /** Return a new Logo Dictionary that contains the bindings of both
	this dictionary and the argument dictionary.  Where conflicting
	bindings occur, the binding in the argument dictionary takes
	precedence.
    */
    public LogoDictionary merge(LogoDictionary d) {
	LogoDictionary result = new LogoDictionary(this);
	result.getMap().putAll(d.getMap());
	return result;
    }

    /** Return a new dictionary that includes the new specified bindings
	as well as the bindings of this dictionary.  The first vector is
	a set of variable names, and the second vector is a corresponding
	set of values. **/
    public LogoDictionary extend(Vector<?> names, Vector<?> values) {
	LogoDictionary result = new LogoDictionary(this);
	for(int i = 0; i < names.size(); i++)
	    result.put((String) names.elementAt(i),
		       (LogoVal) values.elementAt(i));
	return result;
    }
    
    public LogoDictionary extend(ArrayList<?> names, ArrayList<?> values) {
    	LogoDictionary result = new LogoDictionary(this);
    	for(int i = 0; i < names.size(); i++)
    	    result.put((String) names.get(i),
    		       (LogoVal) values.get(i));
    	return result;
        }
    
    
}
